﻿using System;
using System.Collections.Generic;
using NGinnBPM.Lib.Data;
using System.Text;

namespace NGinnBPM.Lib.Interfaces
{

    public class EnableTaskParameters
    {

    }

    /// <summary>
    /// NGinn Environment 
    /// </summary>
    public interface INGEnvironment
    {
        /// <summary>
        /// Start a new process instance
        /// </summary>
        /// <param name="definitionId">Process definition ID</param>
        /// <param name="inputData">Input data for the process</param>
        /// <param name="startedBy">Id of user starting the process</param>
        /// <param name="correlationId">External correlationn id (optional)</param>
        /// <returns></returns>
        string StartProcess(string definitionId, Dictionary<string, object> inputData, string startedBy, string correlationId);

        /// <summary>
        /// Start subprocess
        /// </summary>
        /// <param name="definitionId">Subprocess definition ID</param>
        /// <param name="inputData">Input data</param>
        /// <param name="parentTaskInstance">Instance id of parent task (a subprocess task in a parent process)</param>
        /// <returns></returns>
        string StartSubprocess(string definitionId, Dictionary<string, object> inputData, string parentTaskInstance);

        /// <summary>
        /// Start a new task instance
        /// Warning: if you want to start a multi-instance task, use EnableMultiInstanceTask method
        /// </summary>
        /// <param name="definitionId">Process definition ID</param>
        /// <param name="taskId">ID of task definition</param>
        /// <param name="inputData">Task input data</param>
        /// <param name="parentTaskInstance">Parent composite task instance ID</param>
        /// <param name="parentProcessInstance">Parent process instance ID</param>
        /// <returns>Instance ID of newly created task</returns>
        string EnableTask(string definitionId, string taskId, Dictionary<string, object>  inputData, string parentTaskInstance, string parentProcessInstance);

        /// <summary>
        /// Start new multi-task instace
        /// Warning: task definition must be marked as multi-instance
        /// </summary>
        /// <param name="definitionId"></param>
        /// <param name="taskId"></param>
        /// <param name="inputData"></param>
        /// <param name="parentTaskInstance"></param>
        /// <param name="parentProcessInstance"></param>
        /// <returns>Instance ID of newly created multiinstance task</returns>
        string EnableMultiInstanceTask(string definitionId, string taskId, ICollection<Dictionary<string, object>> inputData, string parentTaskInstance, string parentProcessInstance);
        /// <summary>
        /// Get lists of processes that can be 'kicked', that is, have some work to do
        /// </summary>
        /// <returns>list of process instance IDs</returns>
        IList<string> GetKickableTasks();

        /// <summary>
        /// Kick a task instance. If there is some work to do in process instance, execute some of that work
        /// </summary>
        /// <param name="instanceId">Task instance ID</param>
        void KickTask(string instanceId);

        /// <summary>
        /// Cancel process instance.
        /// </summary>
        /// <param name="instanceId"></param>
        void CancelProcessInstance(string instanceId);

        /// <summary>
        /// Cancels a task instance
        /// </summary>
        /// <param name="instanceId"></param>
        void CancelTaskInstance(string instanceId);

        /// <summary>
        /// Dispatch message to process waiting for it.
        /// </summary>
        /// <param name="messageCorrelationId">Message ID, used for finding the task waiting for the message</param>
        /// <param name="messageBody">Message data content</param>
        void DispatchProcessMessage(string messageCorrelationId, Dictionary<string, object> messageBody);

        /// <summary>
        /// Find active instance of task with given ID in parent block task
        /// </summary>
        /// <param name="taskId"></param>
        /// <param name="parentTaskInstanceId"></param>
        /// <returns></returns>
        string GetActiveInstanceOfTask(string taskId, string parentTaskInstanceId);
        /// <summary>
        /// Returns task state
        /// </summary>
        /// <param name="instanceId"></param>
        /// <returns></returns>
        string GetTaskState(string instanceId);

        /// <summary>
        /// Returns current task data
        /// </summary>
        /// <param name="instanceId"></param>
        /// <returns></returns>
        Dictionary<string, object> GetTaskData(string instanceId);
        /// <summary>
        /// Uppdate task data. Only variables to be modified need to be passed in dataToUpdate.
        /// </summary>
        /// <param name="instanceId"></param>
        /// <param name="dataToUpdate"></param>
        void UpdateTaskData(string instanceId, Dictionary<string, object> dataToUpdate);
        /// <summary>
        /// Force a task to complete
        /// </summary>
        /// <param name="instanceId"></param>
        /// <param name="updatedData"></param>
        /// <param name="completedBy"></param>
        void ForceCompleteTask(string instanceId, Dictionary<string, object> updatedData, string completedBy);

        /// <summary>
        /// Force a task to fail
        /// </summary>
        /// <param name="instanceId"></param>
        /// <param name="errorInfo"></param>
        void ForceFailTask(string instanceId, string errorInfo);

        /// <summary>
        /// Select task (moves from Enabled to Started state)
        /// </summary>
        /// <param name="instanceId"></param>
        void SelectTask(string instanceId);

        /// <summary>
        /// Enable/disable barrier on a place.
        /// If barrier is enabled, tokens will stop at the place and will not be
        /// consumed by following tasks, effectively pausing the process execution.
        /// Disable checkpoint to continue the process execution.
        /// TODO: implement
        /// </summary>
        /// <param name="definitionId"></param>
        /// <param name="placeId"></param>
        /// <param name="enabled"></param>
        void SetBarrier(string definitionId, string placeId, bool enabled);

        /// <summary>
        /// Return barrier state for given place ID
        /// TODO: implement
        /// </summary>
        /// <param name="definitionId"></param>
        /// <param name="placeId"></param>
        /// <returns></returns>
        bool GetBarrier(string definitionId, string placeId);


        /// <summary>
        /// Restart a failed task instance.
        /// Warning: doesn't work for process instances. Restarting a process is done using StartProcess.
        /// </summary>
        /// <param name="instanceId"></param>
        /// <returns></returns>
        void RestartTask(string instanceId);

        /// <summary>
        /// Check if there's an active instance of specified task
        /// in a process instance.
        /// </summary>
        /// <param name="processInstance"></param>
        /// <param name="taskId"></param>
        /// <returns></returns>
        bool IsProcessTaskActive(string processInstance, string taskId);

        /// <summary>
        /// Return information about specified task instance
        /// </summary>
        /// <param name="instanceId"></param>
        /// <returns></returns>
        TaskInstanceInfo GetTaskInstanceInformation(string instanceId);

        /// <summary>
        /// Return information about active task instance. Returns null if there's no active instance
        /// of specified task
        /// </summary>
        /// <param name="processInstanceId">Process instance ID</param>
        /// <param name="taskId">Task definition ID</param>
        /// <returns></returns>
        TaskInstanceInfo GetActiveTaskInstanceInformation(string processInstanceId, string taskId);
        /// <summary>
        /// Return information about all processes with specified external id
        /// </summary>
        /// <param name="extId"></param>
        /// <returns></returns>
        TaskInstanceInfo[] GetProcessesByExternalId(string extId);
        /// <summary>
        /// Return information about active (unfinished) processes with specified external id
        /// </summary>
        /// <param name="extId"></param>
        /// <returns></returns>
        TaskInstanceInfo[] GetActiveProcessesByExternalId(string extId);
        
    }
}
